﻿#region 命名空间

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
using System.Xml;
using System.Xml.Serialization;

#endregion

namespace WWLauncher.Util
{
    /// <summary>
    ///     序列化、反序列化帮助类
    /// </summary>
    public class SerializableHelper
    {
        private static readonly JsonSerializerOptions JsonSettings;
        static SerializableHelper()
        {
            JsonSettings = new JsonSerializerOptions()
            {
                WriteIndented = true,
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping

            };


        }

        /// <summary>
        ///     序列化成一个字节数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static byte[] SerializeToBytes<T>(T t)
        {
            using (var memoryStream = new MemoryStream())
            {
                DataContractSerializer ser = new DataContractSerializer(typeof(T));
                ser.WriteObject(memoryStream, t);
                return memoryStream.ToArray();
            }
        }

        /// <summary>
        ///     序列化成一个字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="df"></param>
        /// <returns>序列化代码</returns>
        public static string SerializeToString<T>(T t, DataFormart df)
        {
            if (df == DataFormart.Xml)
            {
                XmlSerializer s = new XmlSerializer(typeof(T));
                using (Stream stream = new MemoryStream())
                {
                    s.Serialize(stream, t);

                    stream.Seek(0, SeekOrigin.Begin);

                    StreamReader reader = new StreamReader(stream);

                    return reader.ReadToEnd();
                }
            }
            else
            {
                return JsonSerializer.Serialize(t, JsonSettings);
            }
        }

        /// <summary>
        ///     序列化泛型数组为xml文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="fullName"></param>
        /// <param name="df"></param>
        /// <returns>是否序列化成功</returns>
        public static bool Serialize<T>(T t, string fullName, DataFormart df)
        {
            if (df == DataFormart.Xml)
            {
                TextWriter writer = new StreamWriter(fullName);
                try
                {
                    XmlSerializer xmlSerializer = new XmlSerializer(t.GetType());

                    xmlSerializer.Serialize(writer, t);

                    return true;
                }
                catch
                {
                    return false;
                }
                finally
                {
                    writer.Close();
                }
            }
            else if (df == DataFormart.Json)
            {
                using (FileStream _file = new FileStream(fullName, FileMode.Create, FileAccess.ReadWrite))
                {
                    using (var writer = new StreamWriter(_file))
                    {
                        writer.Write(JsonSerializer.Serialize(t, JsonSettings));

                        writer.Flush();
                        writer.Close();
                        _file.Close();
                    }
                }
                return true;
            }
            else
            {
                FileStream fileStream = new FileStream(fullName, FileMode.Create);
#pragma warning disable SYSLIB0011
                var b = new BinaryFormatter();
                b.Serialize(fileStream, t);
                fileStream.Flush();
                fileStream.Close();
                return true;
            }
        }

        /// <summary>
        ///     序列化 Dictionary
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dic"></param>
        /// <param name="fullName"></param>
        /// <returns></returns>
        public static bool Serialize<TKey, TValue>(Dictionary<TKey, TValue> dic, string fullName)
        {
            try
            {
                XmlWriterSettings settings = new XmlWriterSettings
                {
                    Encoding = Encoding.UTF8,
                    Indent = true,
                    ConformanceLevel = ConformanceLevel.Fragment
                };

                using XmlWriter writer = XmlWriter.Create(fullName, settings);
                XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
                XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));


                writer.WriteStartElement("Root");
                foreach (KeyValuePair<TKey, TValue> kv in dic)
                {
                    writer.WriteStartElement("Row");
                    writer.WriteStartElement("Key");
                    keySerializer.Serialize(writer, kv.Key);
                    writer.WriteEndElement();
                    writer.WriteStartElement("Value");
                    valueSerializer.Serialize(writer, kv.Value);
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();


                return true;
            }
            catch
            {
                try
                {
                    File.Delete(fullName);
                }
                catch
                {
                }
                return false;
            }
        }


        /// <summary>
        ///     xml 文件反序列化为泛型数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fi"></param>
        /// <returns></returns>
        public static T DeSerialize<T>(FileInfo fi)
        {
            return DeSerialize<T>(fi, DataFormart.Json);
        }

        /// <summary>
        ///     反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fi"></param>
        /// <param name="df"></param>
        /// <returns></returns>
        public static T DeSerialize<T>(FileInfo fi, DataFormart df)
        {
            lock (fi)
            {
                if (fi.Exists == false)
                    return default(T);
                if (df == DataFormart.Xml)
                {
                    XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

                    FileStream fs = fi.OpenRead();
                    T t;
                    try
                    {
                        t = (T)xmlSerializer.Deserialize(fs);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message + "\r\n" + fi.FullName);
                    }
                    finally
                    {
                        fs.Close();
                    }
                    return t;
                }

                else if (df == DataFormart.Binary)
                {
                    using (var fileStream = new FileStream(fi.FullName, FileMode.Open,
                               FileAccess.Read, FileShare.ReadWrite))
                    {
#pragma warning disable SYSLIB0011
                        var b = new BinaryFormatter();
                        var result = (T)b.Deserialize(fileStream);

                        return result;
                    }

                }
                else
                {
                    var jsonString = new StringBuilder();
                    using (StreamReader sr = new StreamReader(fi.FullName))
                    {
                        while (!sr.EndOfStream)
                        {
                            jsonString.Append(sr.ReadLine());
                        }
                    }
                    var obj = JsonSerializer.Deserialize<T>(jsonString.ToString(), JsonSettings);

                    return obj;

                }
            }
        }
    }

    /// <summary>
    ///     数据格式
    /// </summary>
    public enum DataFormart
    {
        /// <summary>
        ///     二进制
        /// </summary>
        Binary,

        /// <summary>
        ///     Xml格式
        /// </summary>
        Xml,

        /// <summary>
        ///     Json格式
        /// </summary>
        Json
    }
}